﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebNext.UI.Models.Tags;
using System.Collections.Specialized;
using WebNext.UI.Models.Entries;
using WebNext.Domain.Entities;
using System.Text.RegularExpressions;
using WebNext.UI.Models;

namespace WebNext.UI.Utils.ModelBinders
{
	public class EntryEditModelBinder : IModelBinder
	{
		public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
		{
			if (bindingContext.Model != null)
			{
				throw new NotImplementedException("Cannot update instances");
			}
			return this.BindEntryModel(controllerContext.HttpContext.Request.Form);
		}

		private EntryEditViewModel BindEntryModel(NameValueCollection form)
		{
			int id = Convert.ToInt32(form["id"]);
			string title = form["title"];
			string viewTypeName = form["viewType"];
			MainViewType viewType = (MainViewType)Enum.Parse(typeof(MainViewType), viewTypeName);

			EntryEditViewModel entryEditViewModel = new EntryEditViewModel(id, viewType, title, true);

			IList<TagViewModel> selectedTags = this.GetSelectedTags(form);
			foreach (TagViewModel tag in selectedTags)
			{
				entryEditViewModel.Tags.Add(tag);
			}

			IDictionary<int, EntryBindingInfo> bindingInfo = this.GetBindingInfo(form);
			foreach (int order in bindingInfo.Keys.OrderBy(k => k))
			{
				EntryBindingInfo entryBindingInfo = bindingInfo[order];
				EntryElementViewModel elementViewModel = EntryElementFactory.CreateEntryElementViewModel(order, entryBindingInfo.ElementType, entryBindingInfo.Properties);
				entryEditViewModel.Elements.Add(elementViewModel);
			}

			return entryEditViewModel;
		}

		private IList<TagViewModel> GetSelectedTags(NameValueCollection form)
		{
			List<TagViewModel> tags = new List<TagViewModel>();
			string tagPrefix = "tag_";

			foreach (string key in form.Keys)
			{
				if (key.StartsWith("tag_"))
				{
					string tagKeyData = key.Substring(tagPrefix.Length);
					string[] tagData = tagKeyData.Split('_');
					int id = Convert.ToInt32(tagData[0]);
					string name = tagData[1];
					string code = tagData[2];
					tags.Add(new TagViewModel(id, name, code));
				}
			}

			return tags;
		}

		private IDictionary<int, EntryBindingInfo> GetBindingInfo(NameValueCollection form)
		{
			IDictionary<int, EntryBindingInfo> bindingInfo = new Dictionary<int, EntryBindingInfo>();
			Regex regex = new Regex(EntryElementFactory.InputPattern);

			foreach (string key in form.AllKeys.Where(k => regex.IsMatch(k)).OrderBy(k => k))
			{
				string[] inputParts = key.Split(EntryElementFactory.InputSplitter);
				int order = Convert.ToInt32(inputParts[0]);

				if (!bindingInfo.ContainsKey(order))
				{
					EntryElementType elementType = (EntryElementType)Enum.Parse(typeof(EntryElementType), inputParts[1]);
					bindingInfo.Add(order, new EntryBindingInfo(elementType));
				}

				string property = inputParts[2];
				bindingInfo[order].Properties[property] = form[key];
			}

			return bindingInfo;
		}

		private class EntryBindingInfo
		{
			public EntryElementType ElementType
			{
				get;
				private set;
			}

			public IDictionary<string, string> Properties
			{
				get;
				set;
			}

			public EntryBindingInfo(EntryElementType elementType)
			{
				this.ElementType = elementType;
				this.Properties = new Dictionary<string, string>();
			}
		}
	}
}